package org.bsscheduler;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author tblackstone
 */
public class Event {

    private static String defaultFormat = "yyyy-MM-dd H:mm";

    public static int REQUESTED = 1;
    public static int CONFIRMED = 2;
    public static int DECLINED = 3;

    private String id;
    private String creator;
    private Date start;
    private Date end;
    private String title;
    private String description;
    private HashMap<String, String> participants = new HashMap<String, String>();

    public Event(String username) {
        id = UUID.randomUUID().toString();
        creator = username;
    }

    public Event(String username, String uuid) {
        id = uuid;
        creator = username;
    }


    public String getUUID() {
        return id;
    }

    public String getCreator() {
        return creator;
    }

    /**
     * Sets the start date and time for this event. The date must be in the format
     * 'yyyy-MM-dd H:mm'.
     * @param startDate the starting date/time for this event.
     */
    public void setStartDate(String startDate) {
        SimpleDateFormat sdf = new SimpleDateFormat(defaultFormat);
        try {
            start = sdf.parse(startDate);
        } catch (ParseException ex) {
            Logger.getLogger(Event.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public String getStartDate() {
        return getStartDate(defaultFormat);
    }

    public String getStartDate(String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(start);
    }

    public Date getRawStartDate() {
        return start;
    }

    /**
     * Sets the end date and time for this event. The date must be in the format
     * 'yyyy-MM-dd H:mm'.
     * @param endDate the ending date/time for this event.
     */
    public void setEndDate(String endDate) {
        SimpleDateFormat sdf = new SimpleDateFormat(defaultFormat);
        try {
            end = sdf.parse(endDate);
        } catch (ParseException ex) {
            Logger.getLogger(Event.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public String getEndDate() {
        return getEndDate(defaultFormat);
    }

    public String getEndDate(String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(end);
    }

    public Date getRawEndDate() {
        return end;
    }

    /**
     * Sets the title of this event.
     * @param title the new event title
     */
    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public String getTitleEncoded() {
        try {
            return URLEncoder.encode(title, "UTF-8").replace('+', ' ');
        } catch (UnsupportedEncodingException ex) {
            return "";
        }
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    public String getDescriptionEncoded() {
        try {
            return URLEncoder.encode(description, "UTF-8").replace('+', ' ');
        } catch (UnsupportedEncodingException ex) {
            return "";
        }
    }

    /**
     * Adds a participant to this event.
     * @param username the user to invite to participate
     */
    public void addParticipant(String username) {
        setParticipantStatus(username, Event.REQUESTED);
    }

    /**
     * Checks if the given user has been invited to participate in this event.
     * @param username the user to check for
     * @return true if the user has been invited, otherwise false
     */
    public boolean hasParticipant(String username) {
        return participants.containsKey(username);
    }

    public Vector<String> getParticipants() {
        return new Vector(participants.keySet());
    }

    /**
     * Sets the status of a specific event participant. Valid status values are:
     * <ul>
     *   <li><code>Event.REQUESTED</code> - the participant has been requested
     * to attend the event</li>
     *   <li><code>Event.CONFIRMED</code> - the participant has confirmed the
     * appointment</li>
     *   <li><code>Event.DECLINED</code> - the participant has declined to 
     * attend</li>
     * </ul>
     * @param username the user to update the status of
     * @param status the new status
     */
    public void setParticipantStatus(String username, int status) {
        if (status == Event.REQUESTED) {
            participants.put(username, "requested");
        } else if (status == Event.CONFIRMED) {
            participants.put(username, "confirmed");
        } else if (status == Event.DECLINED) {
            participants.put(username, "declined");
        }
    }

    public String getParticipantStatus(String username) {
        if (username.equals(creator)) {
            return "creator";
        }

        if (participants.containsKey(username)) {
            return participants.get(username);
        }

        return "";
    }

    
    @Override
    public boolean equals(Object e) {
        if (e instanceof Event) {
            Event event = (Event) e;
            if (this.getUUID().equals(event.getUUID())) {
                return true;
            }
        }

        return false;
    }

}
